Skip to content

Fix undefined behavior in __pointer_get_max_taggable#11

Open
hobostay wants to merge 1 commit into
microsoft:publicfrom
hobostay:fix-pointer-get-max-taggable-ub
Open

Fix undefined behavior in __pointer_get_max_taggable#11
hobostay wants to merge 1 commit into
microsoft:publicfrom
hobostay:fix-pointer-get-max-taggable-ub

Conversation

@hobostay
Copy link
Copy Markdown

@hobostay hobostay commented May 4, 2026

Summary

  • Fix undefined behavior in __pointer_get_max_taggable() in src/0xc/std/pointer.c

Details

The expression (1 << total) on line 62 uses an int literal 1. In C, shifting an int by >= 31 bits is undefined behavior (per C11 §6.5.7p4: the behavior is undefined if the right operand is greater than or equal to the width of the promoted left operand).

While the current default configurations use POINTER_TAG_BITS_HI=16 and POINTER_TAG_BITS_LO=3 (total=19, which avoids UB), this function is part of a public API and could be used with configurations that have more tag bits. For example, a 32-bit target could legitimately use tag bits summing to 31 or more.

The fix changes (1 << total) to (1ULL << total), ensuring the shift is well-defined for any valid total value (up to 64).

Test plan

  • Existing test suite passes (make test)
  • The change is a single-character fix with no functional impact on current configurations

🤖 Generated with Claude Code

The expression `(1 << total)` uses an `int` literal, which causes
undefined behavior when `total >= 31` (i.e. when the combined tag
bits equal or exceed the width of `int`). Use `1ULL` instead to
ensure the shift is well-defined for any valid tag configuration.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Comment thread src/0xc/std/pointer.c
{
size_t total = POINTER_TAG_BITS_HI + POINTER_TAG_BITS_LO;
return (ptrtag_t)((1 << total) - 1);
return (ptrtag_t)((1ULL << total) - 1);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ptrtag_t is a uint32_t, should we instead be doing (ptrtag_t)1?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants